package divinity.utils.web
{
	import divinity.utils.log.Log;
	import divinity.utils.web.loaders.Assets;
	import divinity.utils.web.loaders.Data;
	import divinity.utils.web.types.Types;
	
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import flash.globalization.DateTimeFormatter;
	import flash.globalization.DateTimeStyle;
	import flash.globalization.LocaleID;
	import flash.utils.getTimer;
	
	public class Web extends EventDispatcher
	{		
		private static var _log:Log=new Log("WEB SERVICE");
		private  var _loaders:Object={};
		private var _name:String;
		private static var _instance:Web=new Web(SLOCK);
		/**
		 * Web is a multipurpuse loader for both binary and ASCII files. It uses sequencing loading for multiple file loading. Each file can be added to different sqeuqnce
		 * and vice versa
		 * 
		 * 
		 * */
		public function Web(lock:Class,target:IEventDispatcher=null)
		{
			super(target);
			if(_instance==null)
			{
				addToLog("Created unique");
			}
			else
			{
				addToLog("Attempt to create another instance");
			}
		}
		public static function get service()
		{
			return _instance;	
		}
		/**
		 * Creates a new loading sequence with name reference
		 * @param seqName name reference
		 * */
		public function newAssetSEQ(seqName:String)
		{
			if(_loaders[seqName]==null)
			{
				addToLog("Created new sequence <"+seqName+">");	
				_loaders[seqName]={};				
				_loaders[seqName].loaded=false;
				_loaders[seqName].elapsed=getTimer();
				_loaders[seqName].asset=new Assets(seqName);
				_loaders[seqName].data=new Data(seqName);
				_loaders[seqName].asset.onComplete(checkSeqLoaded);
				_loaders[seqName].data.onComplete(checkSeqLoaded);
							
			}
			else
			{
				throw new Error("\nSEQUENCE ALREADY EXISTS!\n");
				addToLog("can't create"+seqName+" sequence already exist");				
			}
		}
		private function checkSeqLoaded(e:Object)
		{
			for(var name in _loaders)
			{
				_loaders[name].loaded=true;
				if(!_loaders[name].asset.loaded)
				{
					//trace(name,"asset","not loaded");
					_loaders[name].loaded=false;
				};
				if(!_loaders[name].data.loaded)
				{
					//trace(name,"data","not loaded");
					_loaders[name].loaded=false;
				}
				if(_loaders[name].loaded)
				{
					seqDone(name);
				}
			}
		}
		/**
		 * Adds url reference to sequence which is to be loaded.
		 * @param seqName is the name of sequence
		 * @param url is url reference of the object to be loaded
		 * @param dest is a destination object in which target will loaded content be stored
		 * @param target is target reference of loading content
		 * 
		 * */
		public function add2seq(seqName:String,url:String,destination:Object,target:String,type:String=Types.DATA):void
		{
			//trace("Adding extension: "+url.substring(url.length-3,url.length)); 
			addToLog("Add to sequence <"+seqName+"> "+url);
			switch(type)
			{
				case Types.ASSET:
					_loaders[seqName].asset.addFile(url,destination,target);
					break;
				case Types.DATA:
					_loaders[seqName].data.addFile(url,destination,target,Types.DATA);
					break;
				case Types.DATA_JSON:
					_loaders[seqName].data.addFile(url,destination,target,Types.DATA_JSON);
					break;
				case Types.DATA_XML:
					_loaders[seqName].data.addFile(url,destination,target,Types.DATA_XML);
					break;
				default:
					break;
				
			}
		}
		/**
		 * dispatches Event.COMPLETE on reference after all sequence files are loaded or calls a referenced function
		 * @param seq is reference to sequence name 
		 * @param who can be a function or an EventDispatcher. If referenced to EventDispatcher on loading complete Event.COMPLETE will be dispatched on referenced object.If referenced to a function, that function will be called after all loading is done.
		 * */
		public function alert(seq:String,who:*):void
		{
			if(who is EventDispatcher)
			{
				addToLog("After <"+seq+"> done loading dispatch event on "+who);
			}
			if(who is Function)
			{				
				addToLog("After <"+seq+"> is done loading call "+who);
			}
			_loaders[seq].onComplete=who;			
		}
		private function seqDone(name:Object):void
		{
			var time:int=getTimer();
			_loaders[name].elapsed-=time;
			addToLog("<"+name+"> done loading in "+Math.abs(_loaders[name].elapsed)+" ms")
			if(_loaders[name].onComplete!=null)
			{		
				if(_loaders[name].onComplete is EventDispatcher)
				{
					_loaders[name].onComplete.dispatchEvent(new Event(Event.COMPLETE));
				}
				if(_loaders[name].onComplete is Function)
				{
					_loaders[name].onComplete();
				}	
				_loaders[name]=null;
				delete _loaders[name];
			}
			
		}
		private function addToLog(txt:String)
		{			
			_log.addLog(this,txt);
		
		}
		/**
		 * displays log for WEB loaders
		 * */
		public static function get log():String
		{
			return _log.getLog();
		}
		public static function findLog(str:String):String
		{
			return _log.getLog(str);
		}
		public function get name()
		{
			return _name;
		}
		
	}
}
class SLOCK
{
	
}
